﻿using System;

namespace PageAdmin.Utils.ORM
{

    internal class TableColumnInfoTransform
    {
        /// <summary>
        /// 是否包含默认值转换。
        /// </summary>
        public bool IncludeDefaultTransform { get; set; } = true;

        public string DateTimeDefault { get; set; } = "getdate()";

        public string Transform(TableColumnInfo dataColumnInfo)
        {
            string rv = null;
            string columnName = dataColumnInfo.Name;
            if (string.IsNullOrEmpty(columnName))
            {
                throw new Exception("dataColumnInfo.Name未定义！");
            }
            ColumnDataType dbType = dataColumnInfo.DataType;
            switch (dbType)
            {
                case ColumnDataType.Decimal:
                    rv = "[" + columnName + "] [Decimal]";
                    break;

                case ColumnDataType.BigInt:
                    rv = "[" + columnName + "] [bigint]";
                    break;
                case ColumnDataType.Int:
                    rv = "[" + columnName + "] [int]";
                    break;
                case ColumnDataType.SmallInt:
                    rv = "[" + columnName + "] [smallint]";
                    break;
                case ColumnDataType.TinyInt:
                    rv = "[" + columnName + "] [tinyint]";
                    break;
                case ColumnDataType.Float:
                    rv = "[" + columnName + "] [float]";
                    break;
                case ColumnDataType.NVarChar:
                    rv = "[" + columnName + "] [nvarchar]";
                    break;
                case ColumnDataType.VarChar:
                    rv = "[" + columnName + "] [varchar]";
                    break;

                case ColumnDataType.NChar:
                    rv = "[" + columnName + "] [nchar]";
                    break;
                case ColumnDataType.Char:
                    rv = "[" + columnName + "] [char]";
                    break;

                case ColumnDataType.DateTime:
                    rv = "[" + columnName + "] [datetime]";
                    break;
                case ColumnDataType.Date:
                    rv = "[" + columnName + "] [date]";
                    break;
                case ColumnDataType.Time:
                    rv = "[" + columnName + "] [time]";
                    break;
                default:
                    throw new Exception("dataColumnInfo.DataType未定义！");
                    break;
            }
            rv += FormatLength(dataColumnInfo);
            if (IncludeDefaultTransform)
            {
                rv += FormatDefault(dataColumnInfo);
            }
            rv += FormatCanNullValue(dataColumnInfo);
            return rv;
        }

        /// <summary>
        /// 构造长度
        /// </summary>
        /// <param name="dataColumnInfo"></param>
        /// <returns></returns>
        private string FormatLength(TableColumnInfo dataColumnInfo)
        {
            string rv = "";
            int length = dataColumnInfo.Length;
            ColumnDataType dbType = dataColumnInfo.DataType;
            switch (dbType)
            {
                case ColumnDataType.Decimal:
                    string decimalAccuracy = FormatDecimalAccuracy(dataColumnInfo.DecimalAccuracy);
                    rv = "(" + decimalAccuracy + ")";
                    break;

                case ColumnDataType.BigInt:

                    break;
                case ColumnDataType.Int:

                    break;
                case ColumnDataType.SmallInt:

                    break;
                case ColumnDataType.TinyInt:

                    break;
                case ColumnDataType.Float:

                    break;

                case ColumnDataType.VarChar:
                    if (length == 0)
                    {
                        length = 100;
                    }
                    if (length <= 8000)
                    {
                        rv = "(" + length + ")";
                    }
                    else
                    {
                        rv = "(max)";
                    }
                    break;

                case ColumnDataType.NVarChar:
                    if (length == 0)
                    {
                        length = 100;
                    }
                    if (length <= 4000)
                    {
                        rv = "(" + length + ")";
                    }
                    else
                    {
                        rv = "(max)";
                    }
                    break;

                case ColumnDataType.Char:
                    if (length == 0)
                    {
                        length = 100;
                    }
                    if (length > 8000)
                    {
                        length = 8000;
                    }
                    rv = "(" + length + ")";
                    break;
                case ColumnDataType.NChar:
                    if (length == 0)
                    {
                        length = 100;
                    }
                    if (length > 4000)
                    {
                        length = 4000;
                    }
                    rv = "(" + length + ")";
                    break;
                case ColumnDataType.DateTime:

                    break;
                case ColumnDataType.Date:

                    break;
                case ColumnDataType.Time:
                    break;

            }
            return rv;
        }


        /// <summary>
        /// 构造默认值
        /// </summary>
        /// <param name="dataColumnInfo"></param>
        /// <returns></returns>
        public string FormatDefault(TableColumnInfo dataColumnInfo)
        {
            string rv = "";
            object defaultValue = dataColumnInfo.DefaultValue;
            if (defaultValue == null)
            {
                return rv;
            }
            ColumnDataType dbType = dataColumnInfo.DataType;
            switch (dbType)
            {
                case ColumnDataType.NVarChar:
                case ColumnDataType.VarChar:
                case ColumnDataType.NChar:
                case ColumnDataType.Char:
                    if (string.IsNullOrEmpty(defaultValue.ToString()))
                    {
                        return "";
                    }
                    break;

                case ColumnDataType.DateTime:
                    if (string.IsNullOrEmpty(defaultValue.ToString()))
                    {
                        defaultValue = DateTimeDefault;
                    }
                    break;

                default:
                    
                    break;
            }
            rv = " Default (" + FormatFieldValue(defaultValue, dbType) + ")";
            return rv;
        }


        /// <summary>
        /// 构造默认值
        /// </summary>
        /// <param name="dataColumnInfo"></param>
        /// <returns></returns>
        private string FormatCanNullValue(TableColumnInfo dataColumnInfo)
        {
            string rv = "";
            bool? canNullValue = dataColumnInfo.CanNullValue;
            if (canNullValue == null)
            {
                return rv;
            }
            if ((bool)canNullValue)
            {
                rv = " NULL";
            }
            else
            {
                rv = " NOT NULL";
            }
            return rv;
        }

        /// <summary>
        /// 格式化默认值
        /// </summary>
        /// <param name="value"></param>
        /// <param name="dbDataType"></param>
        /// <returns></returns>
        private static object FormatFieldValue(object value, ColumnDataType dbDataType)
        {
            switch (dbDataType)
            {
                case ColumnDataType.Decimal:
                    decimal decimalValue = 0;
                    decimal.TryParse(value.ToString(), out decimalValue);
                    return decimalValue;
                    break;

                case ColumnDataType.BigInt:
                    long longValue = 0;
                    long.TryParse(value.ToString(), out longValue);
                    return longValue;
                    break;

                case ColumnDataType.Int:
                    int intValue = 0;
                    int.TryParse(value.ToString(), out intValue);
                    return intValue;
                    break;

                case ColumnDataType.SmallInt:
                    short shortValue = 0;
                    short.TryParse(value.ToString(), out shortValue);
                    return shortValue;
                    break;
                case ColumnDataType.TinyInt:
                    byte byteValue = 0;
                    byte.TryParse(value.ToString(), out byteValue);
                    return byteValue;
                    break;

                case ColumnDataType.Float:
                    double doubleValue = 0;
                    double.TryParse(value.ToString(), out doubleValue);
                    return doubleValue;
                    break;

                case ColumnDataType.NVarChar:
                case ColumnDataType.NChar:
                    return "N'" + value.ToString() + "'";
                    break;

                case ColumnDataType.VarChar:
                case ColumnDataType.Char:
                    return "'" + value.ToString() + "'";
                    break;

                case ColumnDataType.DateTime:
                    if (value.ToString() == "getdate()")
                    {
                        return "getdate()";
                    }
                    DateTime dateTimeValue = DateTime.Now;
                    DateTime.TryParse(value.ToString(), out dateTimeValue);
                    return "'" + dateTimeValue.ToString() + "'";
                    break;

            }
            return value;
        }

        /// <summary>
        /// 格式化精度
        /// </summary>
        /// <returns></returns>
        private string FormatDecimalAccuracy(string decimalAccuracy)
        {
            int outInt1=0, outInt2 = 0;
            string[] arrDecimalAccuracy = decimalAccuracy.Split(',');
            if (arrDecimalAccuracy.Length == 1)
            {
                int.TryParse(arrDecimalAccuracy[0], out outInt1);
            }
            else if (arrDecimalAccuracy.Length == 2)
            {
                int.TryParse(arrDecimalAccuracy[0], out outInt1);
                int.TryParse(arrDecimalAccuracy[1], out outInt2);
            }
            if (outInt1 < 1 || outInt1 > 38)
            {
                outInt1 = 10;
            }
            if (outInt2 <0 ||outInt2 > 38)
            {
                outInt2 = 2;
            }
            return outInt1 + "," + outInt2;
        }
    }
}
